Skip to content

feat(integrations): Add startup/checkin endpoints + tooling fixes - #2822

Closed
vikramlc-cognite wants to merge 1 commit into
integrations-part2.2-core-api-testsfrom
integrations-part3-startup-checkin
Closed

feat(integrations): Add startup/checkin endpoints + tooling fixes#2822
vikramlc-cognite wants to merge 1 commit into
integrations-part2.2-core-api-testsfrom
integrations-part3-startup-checkin

Conversation

@vikramlc-cognite

Copy link
Copy Markdown

Summary

Adds the extractor self-registration/heartbeat protocol (startup, checkin) now that cognitedata/service-contracts PR #3378 removed their ifdef: internal marking, plus the retry-idempotency registration and codespell config needed to support the "checkin" identifier. Builds on the API client from #2820/#2821.

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Refactor (no functional change)
  • Documentation update
  • Chore / tooling / CI

What changed

  • New cognite/client/data_classes/integrations/checkin.py: TaskUpdate, ErrorWithTask, StartupRequest, CheckinRequest, CheckinResponse.
  • New IntegrationsAPI.startup() and IntegrationsAPI.checkin() methods, POST-ing to /integrations/startup and /integrations/checkin respectively with the same beta header as the rest of the module.
  • Added integrations/checkin and integrations/startup to the non-idempotent POST pattern list in utils/_url.py, with matching cases in test_api_client.py.
  • .pre-commit-config.yaml: added --ignore-words-list=checkin to the codespell hook args, since "checkin" is the API's real operationId/URL segment and can't be reworded to "check-in" without diverging from the actual wire contract. Passed as a hook arg rather than pyproject.toml's [tool.codespell] because reading TOML config requires tomli/tomllib, which isn't guaranteed available in the hook's isolated environment on Python <3.11.
  • New tests: test_startup/test_checkin in test_api/test_integrations/test_integrations.py, and round-trip tests for all 5 new data classes in test_data_classes/test_integrations.py.

Why it changed

What to focus on during review

  • startup()/checkin() are explicitly documented (Note: in the docstring) as normally only called by extractor implementations as part of the integrations protocol, not typical SDK consumers — worth confirming that framing reads clearly to a reviewer unfamiliar with the extractor side.
  • The codespell hook fix: an earlier attempt via pyproject.toml's [tool.codespell] worked locally but silently failed in CI (Python 3.10 in the hook's isolated venv couldn't parse the TOML without tomli) — this PR's .pre-commit-config.yaml args-based fix is the one that's CI-verified.

Test evidence

  • pytest tests/tests_unit/ -q → 6,708 passed, 8 failed (pre-existing, unrelated: missing geopandas/sympy in the local dev environment — confirmed via git stash/pop A-B testing that these fail identically on master), 6 skipped
  • python scripts/sync_client_codegen/main.py verify → sync mirrors up to date
  • ruff check / ruff format --check → clean (550 files)
  • mypy → no issues (550 source files)
  • Confirmed this branch reconstructs the original unsplit branch byte-for-byte (git diff against it is empty)

Risks and unknowns

  • startup/checkin are part of an extractor-facing heartbeat protocol rather than typical end-user SDK surface — low usage risk for most SDK consumers, but worth a sanity check from someone on the extractors side that the request/response shapes match what real extractors send.

Rollout and rollback

  • Same beta FeaturePreviewWarning gating as the rest of the module. No migrations. Revert is a straight revert of this commit.

Checklist

  • Self-reviewed the diff
  • Tests added or updated (or N/A with reason)
  • Docs updated (or N/A) — N/A, no public docs page exists yet for this beta API
  • No secrets, credentials, or PII committed
  • Breaking changes called out above and communicated to affected teams — N/A, no breaking changes

@vikramlc-cognite
vikramlc-cognite requested review from a team as code owners September 7, 2026 12:15

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements the extractor startup and check-in protocols for the Integrations API, introducing new data classes (StartupRequest, CheckinRequest, CheckinResponse, TaskUpdate, and ErrorWithTask) along with corresponding sync and async client methods. Feedback on the changes suggests removing the custom dump methods in StartupRequest and CheckinRequest because they are redundant and violate the Liskov Substitution Principle by altering the default camel_case parameter value.

Comment on lines +113 to +118
def dump(self, camel_case: bool = True) -> dict[str, Any]:
result = super().dump(camel_case)
result["extractor"] = self.extractor.dump(camel_case)
if self.tasks is not None:
result["tasks"] = [task.dump(camel_case) for task in self.tasks]
return result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The custom dump method in StartupRequest is redundant and violates the Liskov Substitution Principle (LSP) by changing the default value of camel_case from False to True compared to the base class CogniteResource.dump. Since CogniteResource.dump already automatically and recursively serializes nested CogniteResource attributes (like extractor and tasks), this custom implementation can be safely removed to improve maintainability and consistency.

References
  1. Maintainability: Write code that is easy to modify and extend. Consistency: Follow established patterns across the codebase. (link)

Comment on lines +155 to +162
def dump(self, camel_case: bool = True) -> dict[str, Any]:
result = super().dump(camel_case)
if self.task_events is not None:
key = "taskEvents" if camel_case else "task_events"
result[key] = [event.dump(camel_case) for event in self.task_events]
if self.errors is not None:
result["errors"] = [error.dump(camel_case) for error in self.errors]
return result

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The custom dump method in CheckinRequest is redundant and violates the Liskov Substitution Principle (LSP) by changing the default value of camel_case from False to True compared to the base class CogniteResource.dump. Since CogniteResource.dump already automatically and recursively serializes nested CogniteResource attributes (like task_events and errors), this custom implementation can be safely removed to improve maintainability and consistency.

References
  1. Maintainability: Write code that is easy to modify and extend. Consistency: Follow established patterns across the codebase. (link)

@vikramlc-cognite
vikramlc-cognite marked this pull request as draft September 7, 2026 12:21
Adds the extractor self-registration/heartbeat protocol (startup,
checkin) now that service-contracts PR #3378 removed their
ifdef: internal marking, plus the retry-idempotency registration and
codespell config needed to support the "checkin" identifier.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@vikramlc-cognite
vikramlc-cognite force-pushed the integrations-part3-startup-checkin branch from 43aaa1d to 1a77b03 Compare September 7, 2026 12:50
@codecov

codecov Bot commented Sep 8, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 93.26%. Comparing base (eb9d750) to head (1a77b03).

Additional details and impacted files
@@                           Coverage Diff                           @@
##           integrations-part2.2-core-api-tests    #2822      +/-   ##
=======================================================================
+ Coverage                                93.22%   93.26%   +0.03%     
=======================================================================
  Files                                      538      539       +1     
  Lines                                    54531    54650     +119     
=======================================================================
+ Hits                                     50835    50967     +132     
+ Misses                                    3696     3683      -13     
Files with missing lines Coverage Δ
cognite/client/_api/integrations/__init__.py 95.52% <100.00%> (+0.69%) ⬆️
cognite/client/_sync_api/integrations/__init__.py 98.11% <100.00%> (+0.19%) ⬆️
...gnite/client/data_classes/integrations/__init__.py 100.00% <100.00%> (ø)
...ognite/client/data_classes/integrations/checkin.py 100.00% <100.00%> (ø)
cognite/client/utils/_url.py 100.00% <ø> (ø)
...it/test_api/test_integrations/test_integrations.py 100.00% <100.00%> (ø)
tests/tests_unit/test_api_client.py 99.72% <ø> (ø)
.../tests_unit/test_data_classes/test_integrations.py 100.00% <100.00%> (ø)

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@vikramlc-cognite

Copy link
Copy Markdown
Author

Closing out this PR. Will break these stacked PRs based on APIs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants